Promise
本文从js的异步处理出发,引入Promise的概念,并且介绍Promise对象以及其API方法。
js里的异步处理
可以参考这篇文章
js是单线程的,
在js里,异步处理总共有四种方法,其中最常见的一种方法是采用回调函数的方式
function f1(callback){
setTimeout(function(){
callback();
},1000)
}
f1(f2);
另外除了回调函数,事件监听的机制也会进行异步处理。任务的执行不取决于代码的顺序,而是取决于事件是否会发生。
如果是业务逻辑不复杂还好说,可是如果业务逻辑很复杂的话,回调嵌套的很多,代码书写起来会变得很复杂很难看懂。
还有一个问题是,如果有多个异步操作,那么就存在一个处理顺序的问题,代码如何按照希望的顺序执行。
Promise
简介
Promise是抽象异步处理对象以及对其进行各种操作的组件。Promise并不是从js里出现的概念。
Promise则是把类似的异步处理对象和处理规则进行规范化, 并按照采用统一的接口来编写,而采取规定方法之外的写法都会出错。
首先说,Promise是一个对象,所以说这个对象与js里的其他对象没什么不一样的。要说与众不同的地方时,Promise对象充当代理的作用,充当异步操作和回调函数之间的中介
Promise的思想是:每次执行一个异步操作以后,立刻返回一个Promise对象,因为是立刻操作,所以我们可以进行同步操作流程。这个Promise对象有一个then方法,指定回调函数,用于在异步操作执行完后执行回调函数处理。
//换成Promise的写法
new Promise(f5).then(f4).then(f3).then(f2).then(f1)
使用Promise,用同步的写法处理异步操作的代码,使得代码清晰易懂,等一个异步函数处理完成之后,才会执行下一个then里边的函数。这样就避免了前边的多个回调可能引发的顺序问题。
Promise接口
前边说过,Promise接口的作用是,返回一个Promise对象。
一个Promise对象有三种状态
pending 异步操作未完成
resolve 异步操作已成功完成
reject 异步操作失败
至于这三种关系的途径可以描述为两种
pending ---> resolve
pending ---> reject
这种变化只会出现一次。所以,意思是,一个异步操作结束之后只会有两种状态,成功or失败。异步操作成功时,Promise对象返回一个值,对象状态变为resolve,异步操作失败时,对象状态变为reject。
Promise对象用then方法添加回调函数,then方法支持链式调用。
promise.then(onFulfilled, onRejected)
then方法接受两个参数,看名字就知道第一个参数是Promise对象状态时resolve的时候调用,而第二个参数可以省略,表示Promise调用失败状态是reject的时候执行这个回调。
除了then方法,还有一个专门处理异常的方法.
.catch 也可以理解为 promise.then(undefined, onRejected) 。
promise.catch(onRejected)
then和catch两个方法是写到了Promise对象的原型上的,每个Promise对象都可以调用。
Promise对象的生成
ES6提供了原生的Promise对象构造函数,用于生成Promise对象,
var promise = new Promise(function(resolve, reject){
// 异步操作的代码
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
Promise对象接收一个函数作为构造函数的参数,这个函数同样有两个参数,这两个参数是由js引擎提供的函数,不用自己来部署。
resolve函数的作用是把Promise对象的状态从pending变为resolve,在异步操作成功的时候调用,并且将异步操作的结果作为参数传过去。同样的,reject函数的作用是把对象状态从pending变成reject,在失败的时候调用,并且传递结果参数。
接下来,当Promise对象创建成功之后就可以用then方法链式调用了。
Promise对象其他方法
1.Promise.resolve()
一般情况下,我们会用构造函数的方法创建Promise对象。但是,除此之外我们也会有其他方法创建。
静态方法Promise.resolve(value)被认为是new Promise方式创建Promise对象的快捷方式。
Promise.resolve(42).then(function(value){
console.log(value);
})
resolve()会让对象状态立即变成resolved,并且将形参立刻传给下一个回调。
2.Promise.reject()
这个方法类似上一个方法,也是创建Promise对象的快捷方式,但是只会把Promise对象从pending变为rejected。参数是一个异常对象,传递给下一个catch方法或者then方法。
Promise.reject(new Error("BOOM!")).catch(function(error){
console.error(error);
});
3.Promise.all() && Promise.race()
到目前为止,已经学习了创建Promise对象和用then,catch方法来注册回调函数。如果只有一个Promise对象的话很好说,但是如果有多个Promise对象的时候要如何处理呢。
Promise.all 接收一个 promise对象的数组作为参数,当这个数组里的所有promise对象全部变为resolve或reject状态的时候,它才会去调用 .then 方法。
Promise.race 只要有一个promise对象进入 FulFilled 或者 Rejected 状态的话,就会继续进行后面的处理。
4. 每次调用then都会返回一个新创建的promise对象
function f1(v){
console.log(v);
return 2;
}
function f2(v){
console.log(v)
}
Promise.resolve(1).then(f1).then(f2);
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。